package com.koron.rating.change;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.koron.bean.base.Response;
import com.koron.bean.system.role.AppOrgJurisdictionBean;
import com.koron.bean.system.role.UserOwnJurisdictionBean;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.workflow.RedirectQuery;
import com.koron.bean.workflow.WorkflowController;
import com.koron.common.core.annocation.CasUser;
import com.koron.common.core.business.workflow.templates.WorkFlowHandler;
import com.koron.common.core.business.workflow.util.TextUtil;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.StringUtils;
import com.koron.rating.change.bean.*;
import com.koron.rating.change.mapper.UnitChangeBeanMapper;
import com.koron.rating.change.mapper.UnitChangeDetBeanMapper;
import com.koron.rating.change.mapper.UnitEquipmentDetBeanMapper;
import com.koron.rating.change.mapper.UnitOldBeanMapper;
import com.koron.rating.classify.bean.*;
import com.koron.rating.classify.mapper.RatingUnitMapper;
import com.koron.rating.enums.RatingCodeEnum;
import com.koron.rating.rating.bean.RatingOrderDto;
import com.koron.rating.units.RatingUnits;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.koron.ebs.mybatis.ADOConnection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;
import java.util.stream.Collectors;

import static com.koron.rating.enums.RatingChangeEnum.*;
import static com.koron.rating.enums.RatingWorkFlowStatusEnum.*;

@Slf4j
@RequestMapping("/ratingchange")
@RestController
@Api(tags = "设备评级-评级单元变更")
public class RatingChangeController implements WorkflowController {

    private String getCurrDs() {
        return ThreadLocalContext.get().getCurrDs();
    }

    private EamUser getEamUser() {
        return ThreadLocalContext.get();
    }

    //获取权限
    private ArrayList<String> getPower() {
        ArrayList<String> units = CollUtil.newArrayList(getEamUser().getDeptId());
        List<AppOrgJurisdictionBean> appOrgJurisdictionBeans = Optional.ofNullable(getEamUser())
                .map(EamUser::getUserOwnJurisdictionBean)
                .map(UserOwnJurisdictionBean::getAppOrgJurisdictionBeanList).orElse(new ArrayList<>());
        Optional<AppOrgJurisdictionBean> firstopt = appOrgJurisdictionBeans.stream().filter(j -> getEamUser().getAppId().equals(j.getAppId())).findFirst();
        if (firstopt.isPresent()) {
            units.addAll(firstopt.get().getOrgStrList());
        }
        return units;
    }

    @Autowired
    private WorkFlowHandler workflowhandler;

    @Autowired
    private UnitChangeService unitchangeservice;

    @GetMapping("/testpower")
    @ApiOperation(value = "测试权限")
    public Response<List<AppOrgJurisdictionBean>> test() {
        List<AppOrgJurisdictionBean> appOrgJurisdictionBeanList = getEamUser().getUserOwnJurisdictionBean().getAppOrgJurisdictionBeanList();
        return Response.ok(appOrgJurisdictionBeanList);
    }

    @GetMapping("/checkIsAppIng")
    @ApiOperation(value = "新建审批校验")
    public Response checkApprove() {
        Response result = ADOConnection.runTask(getCurrDs(), factory -> {
            UnitChangeBeanMapper mapper = factory.getMapper(UnitChangeBeanMapper.class);
            Map<Object, String> temp = new HashMap<>();
            int checkQty = mapper.countByRatingStatusIn(CollUtil.newArrayList(DRAFT.getLabel(), WAIT_REVIEW.getLabel()));
            if (checkQty > 0) {
                return Response.ok("存在正在审批的变更单据，不可以新建", false);
            } else {
                return Response.ok("成功", true);
            }
        }, Response.class);

        return result;
    }

    @PostMapping("/save")
    @ApiOperation(value = "单据保存")
    public Response<String> insert(@RequestBody UnitChangeBean bean) {
        String id = ADOConnection.runTask(getCurrDs(), factory -> {
            UnitChangeBeanMapper mapper = factory.getMapper(UnitChangeBeanMapper.class);
            if (StrUtil.isNotBlank(bean.getId())) {
                UnitChangeBean unitchangebean = factory.getMapper(UnitChangeBeanMapper.class).selectByPrimaryKey(bean.getId());//获取变更单最后更新时间
                //是否小于数据库最后更新时间
                long between = DateUtil.between(unitchangebean.getUpdateTime(), bean.getUpdateTime(), DateUnit.MS, false);
                if (between < 0) {
                    Assert.isFalse(true, "信息已过期请刷新界面");
                }
                bean.setUpdateTime(new Date());
                mapper.updateByPrimaryKeySelective(bean);
            } else {
                int checkQty = mapper.countByRatingStatusIn(CollUtil.newArrayList(DRAFT.getLabel(), WAIT_REVIEW.getLabel()));
                if (checkQty > 0) {
                    Assert.isFalse(true, "存在正在审批的变更单据，不可以新建");
                }
                bean.setId(CodeTools.getCode32());
                bean.setBillNo(RatingUnits.getRatingChangeCode(RatingCodeEnum.PJDYBG));
                bean.setYear(DateUtil.thisYear());
                bean.setUpdateTime(new Date());
                mapper.insertSelective(bean);

                RatingUnitMapper unitMapper = factory.getMapper(RatingUnitMapper.class);
                // 记录原来单元划分
                UnitOldBeanMapper oldmapper = factory.getMapper(UnitOldBeanMapper.class);
                // 复制对比单元划分
                UnitChangeDetBeanMapper changemapper = factory.getMapper(UnitChangeDetBeanMapper.class);
                List<RatingUnitBean> nowunitlists = unitMapper.queryAll();       //当前单元划分
                List<UnitChangeDetBean> list = new ArrayList();
                for (RatingUnitBean unit : nowunitlists) {
                    UnitChangeDetBean changeunit = Convert.convert(UnitChangeDetBean.class, unit);
                    changeunit.setPrimaryId(CodeTools.getCode32());
                    changeunit.setChangeId(bean.getId());
                    list.add(changeunit);
                }
                log.info("数据总量：{}",list.size());
                long count = list.stream().map(UnitChangeDetBean::getPrimaryId).distinct().count();
                log.info("去重后数据总量：{}",count);
                Lists.partition(list, 300).stream().forEach(p -> {
                    oldmapper.batchInsertChangeDet(p);
                    changemapper.batchInsert(p);
                });

            }
            return bean.getId();
        }, String.class);
        return Response.ok(id);
    }

    @PostMapping("/queryList")
    @ApiOperation(value = "单据列表")
    public Response<PageInfo> queryList(@RequestBody UnitChangeDto querbean) {
        List<RatingOrderDto> list = ADOConnection.runTask(getCurrDs(), factory -> {
            PageHelper.startPage(querbean.getPage(), querbean.getPageSize(), querbean.getOrderBy());
            List<RatingEqDto> tem = factory.getMapper(UnitChangeBeanMapper.class).queryByAll(querbean);
            return tem;
        }, List.class);
        return Response.ok(new PageInfo<>(list));
    }

    @PostMapping("/details")
    @ApiOperation(value = "单据详情")
    public Response<UnitChangeBean> details(@RequestParam("id") String id) {
        UnitChangeBean bean = ADOConnection.runTask(getCurrDs(), factory -> {
            return factory.getMapper(UnitChangeBeanMapper.class).selectByPrimaryKey(id);
        }, UnitChangeBean.class);
        return Response.ok(bean);
    }

    @PostMapping("/changeList")
    @ApiOperation(value = "变更汇总列表")
    public Response<PageInfo> changeList(@RequestBody RatingEqDto querbean) {
        List<RatingOrderDto> list = ADOConnection.runTask(getCurrDs(), factory -> {
            UnitEquipmentDetBeanMapper mapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);
//            PageHelper.startPage(querbean.getPage(), querbean.getPageSize(), querbean.getOrderBy());
            List<UnitEquipmentDetBean> tem = mapper.queryByAll(querbean);
//            tem = tem.stream().filter(l -> l.getDeptId().equals(getEamUser().getDeptId())).collect(Collectors.toList());
            return tem;
        }, List.class);
        return Response.ok(new PageInfo<>(list));
    }

    @GetMapping("/changeListQty")
    @ApiOperation(value = "变更汇总列表数量")
    public Response<Map<String, Integer>> changeListQty(@RequestParam("changeId") String changeId) {
        Map<String, Integer> map = ADOConnection.runTask(getCurrDs(), factory -> {
            UnitEquipmentDetBeanMapper mapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);
            List<UnitEquipmentDetBean> alllist = mapper.queryByAll(new RatingEqDto(changeId));
            Map<String, List<UnitEquipmentDetBean>> qtymap = alllist.stream().collect(Collectors.groupingBy(UnitEquipmentDetBean::getOptType));
            Map<String, Integer> tem = new HashMap<>();
            tem.put(ADD_OPT.getValue(), Optional.ofNullable(qtymap.get(ADD_OPT.getValue())).orElse(new ArrayList<>()).size());
            tem.put(UP_OPT.getValue(), Optional.ofNullable(qtymap.get(UP_OPT.getValue())).orElse(new ArrayList<>()).size());
            tem.put(DEL_OPT.getValue(), Optional.ofNullable(qtymap.get(DEL_OPT.getValue())).orElse(new ArrayList<>()).size());
            return tem;
        }, Map.class);
        return Response.ok(map);
    }

    @GetMapping("/recordDetails")
    @ApiOperation(value = "变更详情")
    public Response<RatringRecordDetailsVo> recorddetails(@RequestParam("changePrimaryId") String changePrimaryId) {
        RatringRecordDetailsVo vo = ADOConnection.runTask(getCurrDs(), factory -> {
            UnitChangeDetBean after = factory.getMapper(UnitChangeDetBeanMapper.class).selectByPrimaryKey(changePrimaryId);
            UnitOldBean befor = factory.getMapper(UnitOldBeanMapper.class).selectByPrimaryKey(changePrimaryId);
            return new RatringRecordDetailsVo(befor, after);
        }, RatringRecordDetailsVo.class);
        return Response.ok(vo);
    }

    @Deprecated
    @PostMapping("/revokeChange")
    @ApiOperation(value = "撤销变更")
    public Response revokeChange(@RequestBody List<UnitEquipmentRevokeDto> dtolist) {
        ADOConnection.runTask(getCurrDs(), factory -> {
            UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
            UnitEquipmentDetBeanMapper eqmapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);

            List<String> list = dtolist.stream().map(UnitEquipmentRevokeDto::getChangePrimaryId).collect(Collectors.toList());//获取变更树主键id
            List<String> eqlist = dtolist.stream().map(UnitEquipmentRevokeDto::getId).collect(Collectors.toList());//获取变更汇总主键id
            mapper.deleteByPrimaryIdIn(list);//批量删除
            List<UnitOldBean> beforlist = factory.getMapper(UnitOldBeanMapper.class).queryAllByPrimaryIdIn(list);

            // 判空，可能出现撤销的都是新增的
            if (CollUtil.isNotEmpty(beforlist)) {
                List<UnitChangeDetBean> collect = beforlist.stream().map(b -> {
                    return Convert.convert(UnitChangeDetBean.class, b);
                }).collect(Collectors.toList());
                mapper.batchInsert(collect);
            }
            eqmapper.deleteByIdIn(eqlist);
            return true;
        }, Boolean.class);
        return Response.ok();
    }

    @PostMapping("/revokeChangeNew")
    @ApiOperation(value = "撤销变更new")
    public Response revokeChangeNew(@RequestBody UnitEquipmentRevokeDto dto) {
        ADOConnection.runTask(getCurrDs(), factory -> {
            UnitChangeDetBeanMapper mapper = factory.getMapper(UnitChangeDetBeanMapper.class);
            UnitEquipmentDetBeanMapper eqmapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);

            UnitChangeDetBean changeDetBean = mapper.selectByPrimaryKey(dto.getChangePrimaryId());//要撤销的变更树记录

            if (mapper.countChildren(changeDetBean.getId(), changeDetBean.getChangeId()) > 0) {
                //匹配 撤销的父节点对应的子节点 的 主键id
                List<String> primaryids = mapper.queryPrimaryIdByChangeIdAndFullPathCodeLike(changeDetBean.getChangeId(), changeDetBean.getId());
                //匹配 撤销的父节点对应的子节点删除
                mapper.deleteByChangeIdAndFullPathCodeLike(changeDetBean.getChangeId(), changeDetBean.getPrimaryId());
                // 删除 子节点的撤销记录
                eqmapper.deleteByChangePrimaryIdIn(primaryids);
            }

            mapper.deleteByPrimaryKey(dto.getChangePrimaryId());//批量删除
            UnitOldBean beforBean = factory.getMapper(UnitOldBeanMapper.class).selectByPrimaryKey(dto.getChangePrimaryId());

            // 判空，可能出现撤销的都是新增的
            if (ObjectUtil.isNotEmpty(beforBean)) {
                mapper.insertSelective(Convert.convert(UnitChangeDetBean.class, beforBean));
            }
            eqmapper.deleteByPrimaryKey(dto.getId());
            return true;
        }, Boolean.class);
        return Response.ok();
    }

    @GetMapping("/deleteChange")
    @ApiOperation(value = "单据删除")
    public Response deleteChange(@RequestParam("id") String id) {
        ADOConnection.runTask(getCurrDs(), factory -> {
            UnitChangeBeanMapper mapper = factory.getMapper(UnitChangeBeanMapper.class);
//            UnitOldBeanMapper oldEqmapper = factory.getMapper(UnitOldBeanMapper.class);//备份树
//            UnitChangeDetBeanMapper changDetmapper = factory.getMapper(UnitChangeDetBeanMapper.class);//变更树
//            UnitEquipmentDetBeanMapper eqchangemapper = factory.getMapper(UnitEquipmentDetBeanMapper.class);//变更汇总
            mapper.deleteJoin(id);
            workflowhandler.delete(id);
            return true;
        }, Boolean.class);
        return Response.ok();
    }


    @PostMapping("/insertBeOne")
    @ApiOperation(value = "新增单元 单个")
    public Response insert(@CasUser @ApiIgnore EamUser user, @RequestBody RatingUnitOneDto dto) {
        dto.setEquipmentId(dto.getDeptId());
        dto.setEquipmentName(dto.getDeptName());
        ArrayList<String> unitTypelist = CollUtil.newArrayList(dto.getUnitType());
        ArrayList<UnitCheckPo> checkPolist = CollUtil.newArrayList(new UnitCheckPo(dto.getEquipmentId(), dto.getEquipmentName(), dto.getUnitType()));
        // 查重
        ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "checkRepeat", void.class, dto.getChangeId(), unitTypelist, checkPolist, null, dto.getUpdateTime());
        UnitChangeDetBean ratingunit = Convert.convert(UnitChangeDetBean.class, dto);
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "insert", Response.class, ratingunit);
    }

    @PostMapping("/insertBatch")
    @ApiOperation(value = "新增单元 批量")
    public Response insertBatch(@CasUser @ApiIgnore EamUser user, @RequestBody RatingUnitChangeBatchDto dto) {
        Assert.isFalse(StringUtils.isEmpty(dto.getDet()), "新增数据不能为空");
        List<String> unitTypelist = dto.getDet().stream().map(RatingUnitOneDto::getUnitType).distinct().collect(Collectors.toList());
        List<UnitCheckPo> checkPolist = dto.getDet().stream().map(r -> {
            return new UnitCheckPo(r.getEquipmentId(), r.getName(), r.getUnitType());
        }).collect(Collectors.toList());
        // 查重
        ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "checkRepeat", void.class, dto.getChangeId(), unitTypelist, checkPolist, null, dto.getUpdateTime());
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "insertBatch", Response.class, dto);
    }

    @PostMapping("/update")
    @ApiOperation(value = "修改单元")
    public Response update(@CasUser @ApiIgnore EamUser user, @RequestBody UnitChangeDetBean ratingunit) {

        ArrayList<String> unitTypelist = CollUtil.newArrayList(ratingunit.getUnitType());
        ArrayList<UnitCheckPo> checkPolist = CollUtil.newArrayList(new UnitCheckPo(ratingunit.getEquipmentId(), ratingunit.getEquipmentName(), ratingunit.getUnitType()));
        // 查重
        ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "checkRepeat", void.class, ratingunit.getChangeId(), unitTypelist, checkPolist, ratingunit.getId(), ratingunit.getUpdateTime());
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "update", Response.class, ratingunit);
    }

    @GetMapping("/delete")
    @ApiOperation(value = "删除单元")
    public Response delete(@CasUser @ApiIgnore EamUser user, String id, String changeId, String updateTime) {
        ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "checkRepeat", void.class, changeId, null, null, null, updateTime);
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "delete", Response.class, id, changeId);
    }

    @GetMapping("/getById")
    @ApiOperation(value = "查询单个单元")
    public Response<UnitChangeDetBean> getById(String id, String changeId) {
        return ADOConnection.runTask(ThreadLocalContext.get().getCurrDs(), unitchangeservice, "getById", Response.class, id, changeId);
    }

    @GetMapping("/getTreeLazy")
    @ApiOperation(value = "查询设备单元树形结构（懒加载）")
    public Response<List<UnitChangeDetBean>> getTreeLazy(@CasUser @ApiIgnore EamUser user, String parentId, String changeId) {
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "getTreeLazy", Response.class, parentId, changeId);
    }

    @GetMapping("/getFloor")
    @ApiOperation(value = "获取层级列表")
    public Response<List<Select>> getFloor(@CasUser @ApiIgnore EamUser user, String parentId, String id, String changeId) {
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "getFloor", Response.class, parentId, id, changeId);
    }

    @GetMapping("/searchByName")
    @ApiOperation(value = "根据设单元称模糊查询")
    public Response<List<UnitChangeDetBean>> searchByName(@CasUser @ApiIgnore EamUser user, String name, String deptId, String changeId) {
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "searchByName", Response.class, name, deptId, changeId);
    }

    @GetMapping("/getParentIds")
    @ApiOperation(value = "获取某个节点的所有父节点")
    public Response<List<String>> getParentIds(@CasUser @ApiIgnore EamUser user, String id, String changeId) {
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "getParentIds", Response.class, id, changeId);
    }

//    @GetMapping("/getLeftUpperRatingUnitByDeptId")
//    @ApiOperation(value = "获取同组织下，最左上的设备台账")
//    public Response<UnitChangeDetBean> getLeftUpperRatingUnitByDeptId(@CasUser @ApiIgnore EamUser user, String deptId) {
//        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "getLeftUpperRatingUnitByDeptId", Response.class, deptId);
//    }

    @GetMapping("/changeSort")
    @ApiOperation(value = "同父级下 上下移")
    public Response<UnitChangeDetBean> changeSort(@CasUser @ApiIgnore EamUser user, RatingUnitSortDto dto) {
        return ADOConnection.runTask(user.getCurrDs(), unitchangeservice, "changeSort", Response.class, dto);
    }


    @GetMapping("/queryRatingUnitTypeGroup")
    @ApiOperation(value = "各类型统计数")
    public Response<List<RatingUnitTypeGroupVo>> queryRatingUnitTypeGroup(@RequestParam("deptId") String deptId, String changeId) {
        List<RatingUnitTypeGroupVo> list = ADOConnection.runTask(getCurrDs(), factory -> {
            List<RatingUnitTypeGroupVo> temlist = factory.getMapper(UnitChangeDetBeanMapper.class).queryRatingUnitTypeGroup(deptId, changeId);
            int sum = temlist.stream().mapToInt(RatingUnitTypeGroupVo::getSubtotal).sum();
            temlist.stream().forEach(t -> t.setTotal(sum));
            return temlist;
        }, List.class);
        return Response.ok(list);
    }


    @Override
    @ApiOperation("修改业务状态, 非前端接口")
    public Response<Object> updateState(@RequestBody RedirectQuery redirectQuery) {
        log.info("工作流更新： {}", JSON.toJSONString(redirectQuery));
        Map<String, String> infoMap = TextUtil.toMapFromString(redirectQuery.getFormVariables());
        log.info("流程状态：" + redirectQuery.getCurNodeCode());
        if (redirectQuery.getCurNodeCode().equals("call-unit")) {
            ADOConnection.runTask(getCurrDs(), factory -> {
                factory.getMapper(UnitChangeBeanMapper.class).updateRatingStatusById(WAIT_REVIEW.getLabel(), infoMap.get("id"));
                return true;
            }, Boolean.class);
        }
        return Response.success();
    }

    @Override
    @ApiOperation("结束时的修改方法, 非前端接口")
    public Response<Object> updateEnd(@RequestBody RedirectQuery redirectQuery) {
        log.info("工作流完结 ： {}", JSON.toJSONString(redirectQuery));
        Map<String, String> infoMap = TextUtil.toMapFromString(redirectQuery.getFormVariables());
        //流程结束
        ADOConnection.runTask(getCurrDs(), factory -> {
            factory.getMapper(UnitChangeBeanMapper.class).updateRatingStatusById(APPROVED.getLabel(), infoMap.get("id"));
            RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
            UnitChangeDetBeanMapper detmapper = factory.getMapper(UnitChangeDetBeanMapper.class);
            List<UnitChangeDetBean> detlist = detmapper.queryByChangeId(infoMap.get("id"));
            List<RatingUnitBean> insertlist = detlist.stream().map(d -> {
                return Convert.convert(RatingUnitBean.class, d);
            }).collect(Collectors.toList());
            mapper.deleteAll(); //删除所有哦单元划分
            Lists.partition(insertlist, 300).stream().forEach(d -> mapper.batchInsert(d));//插入变更后单元划分
            return true;
        }, Boolean.class);
        return Response.success();
    }

    @Override
    @ApiOperation("作废时的修改方法, 非前端接口")
    public Response<Object> updateCancel(@RequestBody RedirectQuery redirectQuery) {
        log.info("updateCancel = {}", JSON.toJSONString(redirectQuery));
        return Response.success();
    }

    @Deprecated
    @ApiOperation("流程手动删除")
    @GetMapping("/deleteWorkflow")
    public Response deleteWorkflow(@RequestParam("id") String id) {
        workflowhandler.delete(id);
        return Response.success();
    }
}
